package cn.cas.mango.service;

import cn.cas.mango.dto.HotChartValue;
import cn.cas.mango.dto.Material;
import cn.cas.mango.dto.Message;
import cn.cas.mango.dto.News;
import cn.cas.mango.dto.param.MaterialParam;
import cn.cas.mango.util.EsTypeTransUtil;
import cn.cas.mango.util.Pair;
import cn.cas.mango.util.RenderDateUtil;
import cn.cas.mango.util.RequestUtil.BuildMaterialRequest;
import cn.cas.mango.util.ResponseUtil.ResponseUtil;
import cn.cas.mango.util.TimeUtil;
import cn.cas.mango.util.paramCheck.MaterialParamCheckUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.Time;
import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.util.NamedValue;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * todo material搜索的服务程序
 * <p>
 * TODO 好像漏了个按顺序输出的东西
 */
@Service
@Slf4j
public class MaterialSearchService {
  // 客户端操作
  @Autowired
  private ElasticsearchClient elasticsearchClient;
  // 基本配置项application.properties中的
  @Autowired
  private ConfigService config;
  @Autowired
  private BuildMaterialRequest buildMaterialRequest;
  private final int monthShow = 2;


  /**
   *
   * @param materialParam, 资料的参数
   * @param filterUid, 是否要过滤uid
   * @return
   */
  private SearchRequest.Builder chooseQueryType(MaterialParam materialParam, SortOptions sortOptions, boolean filterUid) {
    SearchRequest.Builder searchRequest;
    if (materialParam.getSortType().equals("sim")) {
      if (materialParam.getQueryStr().contains("+") || materialParam.getQueryStr().contains("-")
      ) {
        searchRequest = buildMaterialRequest.buildMaterialQueryStrRequest(materialParam, filterUid)
            .sort(sortOptions)
            ;
      } else {
        searchRequest = buildMaterialRequest.buildMaterialRequest(materialParam, filterUid)
            .sort(sortOptions)
            ;
      }
    } else {
      SortOptions scoreOptions = SortOptions.of(
          s -> s.field(f -> f.field("_score").order(SortOrder.Desc)));
      if (materialParam.getQueryStr().contains("+") || materialParam.getQueryStr().contains("-")
          ) {
        searchRequest = buildMaterialRequest.buildMaterialQueryStrRequest(materialParam, filterUid)
            .sort(sortOptions, scoreOptions);
      } else {
        searchRequest = buildMaterialRequest.buildMaterialRequest(materialParam, filterUid)
            .sort(sortOptions, scoreOptions);
      }
    }
    return searchRequest;
  }

  public Message getWorkMaterialList(MaterialParam materialParam) throws IOException {
    long start = System.currentTimeMillis();

    // 1.参数检查
    Map<String, Object> errMessage = MaterialParamCheckUtil.checkParam(materialParam, config.getMaterialPageSize());
    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }

    materialParam = MaterialParam.getFromFormData(errMessage);

    // 2.处理参数转换为对应的请求
    List<Object> sorts = materialParam.get3Sorts();
    SortOptions sortOptions = (SortOptions) sorts.get(2);
    SearchRequest searchRequest = chooseQueryType(materialParam, sortOptions, true).build();
//    if (materialParam.getSortType().equals("sim")) {
//      if (materialParam.getQueryStr().contains("+") || materialParam.getQueryStr().contains("-")
//      ) {
//        searchRequest = buildMaterialRequest.buildMaterialQueryStrRequest(materialParam)
//          .sort(sortOptions)
//          .build();
//      } else {
//        searchRequest = buildMaterialRequest.buildMaterialRequest(materialParam)
//          .sort(sortOptions)
//          .build();
//      }
//    } else {
//      SortOptions scoreOptions = SortOptions.of(
//        s -> s.field(f -> f.field("_score").order(SortOrder.Desc)));
//      if (materialParam.getQueryStr().contains("+") || materialParam.getQueryStr().contains("-")
//        || (materialParam.getQueryStr().contains("(") && materialParam.getQueryStr().contains(")"))) {
//        searchRequest = buildMaterialRequest.buildMaterialQueryStrRequest(materialParam)
//          .sort(sortOptions, scoreOptions)
//          .build();
//      } else {
//        searchRequest = buildMaterialRequest.buildMaterialRequest(materialParam)
//          .sort(sortOptions, scoreOptions)
//          .build();
//      }
//    }

    //3.发送请求
    log.info("【{}-{}-{}】, Search Request Json:{}",
        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        searchRequest.toString().split("typed_keys=true")[1]);
    long searchStart = System.currentTimeMillis();
    SearchResponse<Material> searchResponse = elasticsearchClient.search(searchRequest, Material.class);
    long searchEnd = System.currentTimeMillis();

    List<JSONObject> doc = new ArrayList<>();
    HitsMetadata<Material> hits = searchResponse.hits();
    TotalHits total = hits.total();
    log.info("【{}-{}-{}】hit number: {}, search time: {}s", materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(), total, (searchEnd - searchStart) / 1000.0);

    // 4.包装查询结果
    List<Hit<Material>> hitsList = hits.hits();
    for (Hit<Material> newsHit : hitsList) {
      assert newsHit.source() != null;
      addLink2Doc(doc, newsHit, materialParam);
    }

    assert total != null;
    long totalValue = total.value();

    JSONObject data = new JSONObject();

    data.put("totalResults", totalValue);
    data.put("document", doc);
    data.put("time", System.currentTimeMillis() - start);
    return Message.builder().code(200).message("success.").data(data).build();
  }

  private JSONObject addLink2Doc(List<JSONObject> doc, Hit<Material> materialHit, MaterialParam materialParam) {
    Material hitSource = materialHit.source();
    JSONObject link = new JSONObject();
    assert hitSource != null;
    Map<String, List<String>> highlightMap = materialHit.highlight();
    link.put("id", hitSource.getId());
    ResponseUtil.putMaterialTitleContent(highlightMap, link, materialHit.source());
    link.put("material_date", hitSource.getMaterialDate());
    link.put("material_type", hitSource.getMaterialType());
    link.put("material_security", hitSource.getMaterialSecurity());
    link.put("material_category", hitSource.getMaterialCategory());
    link.put("material_source", hitSource.getMaterialSource());
    link.put("material_aggre", hitSource.getMaterialSource() + "-" + hitSource.getMaterialCategory());
    link.put("materialFor", materialParam.getMaterialFor());
    doc.add(link);
    return link;
  }

  private int getColorCast(Integer[] array, int key) {
    if (array == null || array.length == 0) {
      return 1;
    }
    int min = array[0];
    int max = array[array.length - 1];
    if (max - min == 0) {
      return 1;
    }
    int a = (int)(((double)(key - min) * 4) / (max - min) + 1);
    if (a == 5)
      a = 4;
    return a;
  }



  /**
   * 获取推荐文章
   */
  public Message getReferInfo(MaterialParam materialParam) throws IOException {
    TimeUtil timeUtil = new TimeUtil();
    // 1.参数检查
    Map<String, Object> errMessage = MaterialParamCheckUtil.checkParam(materialParam, config.getMaterialPageSize());
    if (Strings.isBlank(materialParam.getId())) {
      errMessage.put("isSuccess", "必须传递id");
    }
    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }
    if (Strings.isBlank(materialParam.getEndDate()) ||
        Strings.isBlank(materialParam.getStartDate())) {
      Pair<String, String> aYearStartEnd = RenderDateUtil.getRecent1Year();
      materialParam.setStartDate(aYearStartEnd.getKey());
      materialParam.setEndDate(aYearStartEnd.getValue());
    }
    materialParam.setSortType("sim");

    if (materialParam.getDegree() == null) materialParam.setDegree(0.3);
    materialParam.setSearchType("false");
    List<Hit<Material>> hits = searchById(materialParam, new String[]{"material_keywords"});
    if (hits.isEmpty()) {
      return Message.unSuccess("id 不正确");
    }

    List<String> searchingKeywords = new ArrayList<>();
      assert hits.get(0).source() != null;

      searchingKeywords.addAll(EsTypeTransUtil.entity2List(hits.get(0).source().getMaterialKeywords()));
    materialParam.setQueryStr(String.join(" ", searchingKeywords));
    materialParam.setPageSize(10);

    LinkedHashMap<String, Object> map = new LinkedHashMap<>();
    SearchRequest.Builder requestBuilder =  buildMaterialRequest.buildMaterialRequest(materialParam, true).sort((SortOptions) materialParam.get3Sorts().get(2));;
    map.put("axis", getCountStatInfo(materialParam, requestBuilder));
    JSONObject sim = new JSONObject();
    requestBuilder = buildMaterialRequest.buildMaterialRequest(materialParam, true).sort((SortOptions) materialParam.get3Sorts().get(2));
    SearchRequest searchRequest = requestBuilder.build();
    getSimNews(getResponseEntity(searchRequest, materialParam), sim, materialParam);
    map.put("simNews", sim);
    log.info("【{}-{}-{}】, get refer total cost: {}s",
        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        timeUtil.getCost()
        );
    return Message.builder().code(200).message("success.").data(map).build();
  }

  private ResponseEntity<JSONObject> getResponseEntity(SearchRequest searchRequest, MaterialParam materialParam) {
    String queryJsonStr = searchRequest.toString().split("typed_keys=true")[1];
    JSONObject queryJson = JSONObject.parseObject(queryJsonStr);
    log.info("【{}-{}-{}】, Search Request Json:{}",
        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        queryJson);
    RestTemplateBuilder builder = new RestTemplateBuilder();
    RestTemplate restTemplate = builder.basicAuthentication(config.getUsername(), config.getPassword()).build();
    String url = "http://" + config.getHost() + ":" + config.getPort() + "/" + config.getMaterialDepartment().get(materialParam.getDepartment()) + "/_search";
    ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, queryJson,
        JSONObject.class);
    return responseEntity;
  }

  private Map<String, Object> getCountStatInfo(MaterialParam materialParam, SearchRequest.Builder requestBuilder) {
    TimeUtil time = new TimeUtil();
    final List<String> axisDay = RenderDateUtil.getDistanceDate(materialParam.getStartDate(),
        materialParam.getEndDate());
    final List<String> getDistanceMonth = RenderDateUtil.getDistanceMonth(axisDay);
    final List<String> getDistanceYear = RenderDateUtil.getDistanceYear(axisDay);
    NamedValue<SortOrder> order = new NamedValue<>("_key", SortOrder.Asc);
    String field = "material_date";
    requestBuilder
        .aggregations("count-day",
            aggBuilder -> aggBuilder.dateHistogram(
                gram -> gram.field(field).calendarInterval(CalendarInterval.Day)
                    .format("yyyy-MM-dd")
                    .minDocCount(1).order(order))
        );
    if (getDistanceMonth.size() > monthShow) {
      requestBuilder
          .aggregations("count-month",
              aggBuilder -> aggBuilder.dateHistogram(
                  gram -> gram.field(field).calendarInterval(CalendarInterval.Month)
                      .format("yyyy-MM")
                      .minDocCount(1).order(order))
          )

      ;
    }
    if (axisDay.size() > 365 * 3 + 1) {
      requestBuilder
          .aggregations("count-year",
              aggBuilder -> aggBuilder.dateHistogram(
                  gram -> gram.field(field).calendarInterval(CalendarInterval.Year)
                      .format("yyyy")
                      .minDocCount(1).order(order)))
      ;
    }
    SearchRequest searchRequest = requestBuilder.build();


    JSONObject responseJson = Objects.requireNonNull(getResponseEntity(searchRequest, materialParam).getBody())
        .getJSONObject("aggregations");
    log.info("【{}-{}-{}】, Get 柱状图 query :{} s",
        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        time.getCost());
    final Map<Integer, String> colorMap = config.getColorMap();
    final LinkedHashMap<String, List<String>> monthMap = RenderDateUtil.getDistanceMonthMap(
        axisDay);
    //处理按天统计数据
    JSONArray countDayArray = responseJson.getJSONObject("count-day").getJSONArray("buckets");
    Map<String, Integer> dayCountMap = new HashMap<>();


    for (Object row : countDayArray) {
      JSONObject rowJson = (JSONObject) row;
      String day = rowJson.getString("key_as_string");
      Integer count = rowJson.getInteger("doc_count");
      dayCountMap.put(day, count);
    }
    List<HotChartValue> countDayList = new ArrayList<>();
    List<Integer> dayCount = new ArrayList<>();
    List<Float> dayHot = new ArrayList<>();
    for (String day : axisDay) {
      HotChartValue countValue = new HotChartValue();
      countValue.setDate(day);
      if (dayCountMap.get(day) != null) {
        countValue.setValue(dayCountMap.get(day));
        dayCount.add(dayCountMap.get(day));
      } else {
        countValue.setValue(0);
        dayCount.add(0);
        dayHot.add(0.0F);
      }
      countDayList.add(countValue);
    }
    Integer[] countArray = dayCount.stream().filter(x->x!=0).collect(Collectors.toList()).toArray(new Integer[0]);
    if (countArray.length != 0)
      Arrays.sort(countArray);

    for (HotChartValue value : countDayList) {
      int value1 = (int)value.getValue();
      int a = getColorCast(countArray, value1);
      if (value1 != 0)
        value.setColor(colorMap.get(a));
    }
//    log.info("数量按天处理End:{}s", time.getCost());

    //处理按月统计数据
    List<HotChartValue> monthCountList = new ArrayList<>();


    if (getDistanceMonth.size() > monthShow) {
      JSONArray countMonthArray = responseJson.getJSONObject("count-month").getJSONArray("buckets");
      Map<String, Integer> monthCountMap = new HashMap<>();
      for (Object row : countMonthArray) {
        JSONObject rowJson = (JSONObject) row;
        String day = rowJson.getString("key_as_string");
        Integer count = rowJson.getInteger("doc_count");
        monthCountMap.put(day, count);
      }

      List<Integer> monthCount = new ArrayList<>();
      for (String day : getDistanceMonth) {
        HotChartValue countValue = new HotChartValue();
        countValue.setDate(day);
        if (monthCountMap.get(day) != null) {
          countValue.setValue(monthCountMap.get(day));
          monthCount.add(monthCountMap.get(day));
        } else {
          countValue.setValue(0);
          monthCount.add(0);
        }
        monthCountList.add(countValue);
      }

      Integer[] monthArray =  monthCount.stream().filter(x->x!=0).collect(Collectors.toList()).toArray(new Integer[0]);
      if (monthArray.length != 0)
        Arrays.sort(monthArray);

      for (HotChartValue value : monthCountList) {
        int value1 = (int) value.getValue();
        int a = getColorCast(monthArray, value1);
        if (value1 != 0)
          value.setColor(colorMap.get(a));
      }
    }
//    log.info("数量按月处理End:{}s", time.getCost());
    // 处理按年统计数据
    List<HotChartValue> yearCountList = new ArrayList<>();

    if (axisDay.size() > 365 * 3 + 1) {
      JSONArray countYearArray = responseJson.getJSONObject("count-year").getJSONArray("buckets");
      Map<String, Integer> yearCountMap = new HashMap<>();
      for (Object row : countYearArray) {
        JSONObject rowJson = (JSONObject) row;
        String day = rowJson.getString("key_as_string");
        Integer count = rowJson.getInteger("doc_count");
        yearCountMap.put(day, count);

      }
      yearCountList = new ArrayList<>();
      List<Integer> yearCount = new ArrayList<>();
      for (String day : getDistanceYear) {
        HotChartValue countValue = new HotChartValue();
        HotChartValue hotValue = new HotChartValue();
        countValue.setDate(day);
        hotValue.setDate(day);
        if (yearCountMap.get(day) != null) {
          countValue.setValue(yearCountMap.get(day));
          yearCount.add(yearCountMap.get(day));
        } else {
          countValue.setValue(0);
          yearCount.add(0);
        }
        yearCountList.add(countValue);
      }

      Integer[] yearArray = yearCount.stream().filter(x->x!=0).collect(Collectors.toList()).toArray(new Integer[0]);
      if (yearArray.length != 0)
        Arrays.sort(yearArray);

      for (HotChartValue value : yearCountList) {
        int value1 = (int)value.getValue();
        int a = getColorCast(yearArray, value1);
        if (value1 != 0)
          value.setColor(colorMap.get(a));
      }
    }
//    log.info("数量按年处理End:{}s",time.getCost());

    Map<String, Object> countStatInfo = new HashMap<>();
    String[] tag;
    if (axisDay.size() > 365 * 3 + 1) {
      countStatInfo.put("statistic", new List[]{
          countDayList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList()),
          monthCountList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList()),
          yearCountList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList())
      });
      tag = new String[]{"日", "月", "年"};
    } else if (getDistanceMonth.size() < monthShow + 1) {
      countStatInfo.put("statistic", new List[]{
          countDayList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList())
      });
      tag = new String[]{"日"};
    } else {
      countStatInfo.put("statistic", new List[]{
          countDayList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList()),
          monthCountList.stream().map(hotChartValue->hotChartValue.getJsonObject2()).collect(Collectors.toList())
      });
      tag = new String[]{"日", "月"};
    }
    countStatInfo.put("tag", tag);
    return countStatInfo;
  }

  public Message getKeywords(MaterialParam materialParam) {
    TimeUtil recordGetKeywordsTime = new TimeUtil();
    // 1.参数检查
    Map<String, Object> errMessage = MaterialParamCheckUtil.checkParam(materialParam, config.getMaterialPageSize());
    if (Strings.isBlank(materialParam.getId())) {
      errMessage.put("isSuccess", "必须传递id");
    }
    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }List<Hit<Material>> hits = null;
    try {
      hits = searchById(materialParam, new String[]{"id", "material_date", "material_keywords",
          "material_source", "material_summary", "material_title"});
      if (hits.isEmpty()) {
        isSuccess = "该id没有查询结果，请检查id";
        return Message.unSuccess(isSuccess);
      }
    } catch (IOException e) {
      log.error(e.toString());
    }
    assert hits != null;
    Hit<Material> newsHit = hits.get(0);
    Material material = newsHit.source();
    JSONObject document = new JSONObject();
    document.put("id", materialParam.getId());
    document.put("materialFor", materialParam.getMaterialFor());
    document.put("material_date", material.getMaterialDate());
    document.put("material_keywords", processKeywords(material));
    document.put("material_source", material.getMaterialSource());
    document.put("material_summary", material.getMaterialSummary());
    document.put("material_title", material.getMaterialTitle());
    JSONObject data = new JSONObject();
    data.put("document", document);
    data.put("info", new JSONObject());
    log.info("【{}-{}-{}】, get keywords success, cost: {}",
        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        recordGetKeywordsTime.getCost());
    return Message.builder().code(200).message("success.").data(data).build();
  }




  private List<String> processKeywords(Material material) {
    List<String> list = getList(material.getMaterialKeywords());
    return list;
  }

  private List<String> getList(Object o) {
    List<String> finalRes = new ArrayList<>();
    if (o instanceof String) {
      finalRes.add((String) o);
    } else if (o instanceof List) {
      finalRes.addAll((List) o);
    }
    return finalRes;
  }

  private List<Hit<Material>> searchById(MaterialParam materialParam, String[] includes) throws IOException {

    SearchRequest query = SearchRequest.of(
        s -> s.index(config.getMaterialDepartment().get(materialParam.getDepartment()))
            .query(
                q -> q.term(
                    e -> e.field("id").value(v -> v.stringValue(materialParam.getId()))
                )
            ).size(10).source(source -> source.filter(f -> f.includes(Arrays.asList(includes))))
    );
    System.out.println(query);

//    query = SearchRequest.of(s->s.index("t_twitter_post").query(
//        q->q.bool(
//            b->b.should(x->x.wildcard(m->m.field("author_name").wildcard("*Josh*")
//            )).should(x->x.wildcard(m->m.field("post_content").wildcard("first*")
//            )).minimumShouldMatch("1"))).from(10).size(10));

    SearchResponse<Material> ret = elasticsearchClient.search(
        query, Material.class);
    return ret.hits().hits();
  }

  private void getSimNews(ResponseEntity<JSONObject> responseEntity, JSONObject link, MaterialParam materialParam) {
    JSONArray jsonArray = responseEntity.getBody().getJSONObject("hits").getJSONArray("hits");
    if (jsonArray == null || jsonArray.isEmpty()) {
      jsonArray = new JSONArray();
    }
    List<JSONObject> hits = new ArrayList<>();

    Map<String, Map<String, List<String>>> map2Highlight = new HashMap<>();
    for (Object o: jsonArray) {
      JSONObject temp = (JSONObject) o;
      JSONObject source = temp.getJSONObject("_source");
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("id", source.get("id"));
      jsonObject.put("materialFor", materialParam.getMaterialFor());
      jsonObject.put("material_category", source.get("material_category"));
      jsonObject.put("material_date", source.get("material_date"));
      jsonObject.put("material_security", source.get("material_security"));
      jsonObject.put("material_source", source.get("material_source"));
      jsonObject.put("material_type", source.get("material_type"));
      jsonObject.put("material_title", source.get("material_title"));
      jsonObject.put("material_content", source.get("material_content"));
      JSONObject highlight = temp.getJSONObject("highlight");
      HashMap<String, List<String>> tempMap = new HashMap<>();
      for (Object s: highlight.keySet()) {
        Object value = highlight.get(s);
        tempMap.put((String)s, (List<String>)value);
      }


      map2Highlight.put((String) jsonObject.get("id"), tempMap);
      hits.add(jsonObject);
    }

    List<JSONObject> newsList = new ArrayList<>();
    for (JSONObject object: hits) {

      ResponseUtil.putMaterialTitleContent(map2Highlight.get(object.get("id")), object, object);
      newsList.add(object);
    }

    link.put("currentPage", materialParam.getCurrentPage());
    link.put("materials", newsList);
    Integer num = (responseEntity.getBody().getJSONObject("hits").getJSONObject("total").getInteger("value"));
    link.put("totalResults", (
        num
    ));
  }

  public Message queryAnalysis(MaterialParam materialParam) {
    TimeUtil timeUtil = new TimeUtil();
    // 1.参数检查
    Map<String, Object> errMessage = MaterialParamCheckUtil.checkParam(materialParam, config.getMaterialPageSize());

    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }
    if (Strings.isBlank(materialParam.getEndDate()) ||
        Strings.isBlank(materialParam.getStartDate())) {
      Pair<String, String> aYearStartEnd = RenderDateUtil.getRecent3Year();
      materialParam.setStartDate(aYearStartEnd.getKey());
      materialParam.setEndDate(aYearStartEnd.getValue());
    }
    materialParam.setSortType("sim");
    if (materialParam.getDegree() == null) materialParam.setDegree(0.3);
    materialParam.setSearchType("false");
    materialParam.setPageSize(10);
    SearchRequest.Builder requestBuilder = chooseQueryType(materialParam, (SortOptions) materialParam.get3Sorts().get(2), true);
    Map<String, Object> countStatInfo = getCountStatInfo(materialParam, requestBuilder);
    log.info("【{}-{}-{}】 queryAnalysis total cost: {}s ",

        materialParam.getDepartment(),
        config.getMaterialDepartment().get(materialParam.getDepartment()),
        materialParam.getUuid(),
        timeUtil.getCost());
    return Message.builder().message("success").code(200).data(countStatInfo).build();

  }


  public Message clickReferAxis(MaterialParam materialParam) throws IOException {
    // 获取日期
    Pair<String, String> startEnd = RenderDateUtil.getStartEnd(materialParam.getDate());
    materialParam.setStartDate(startEnd.getKey());
    materialParam.setEndDate(startEnd.getValue());


    Map<String, Object> errMessage = MaterialParamCheckUtil.checkParam(materialParam, config.getMaterialPageSize());

    String isSuccess = (String) errMessage.get("isSuccess");
    if (!isSuccess.equals("ok")) {
      log.error(isSuccess);
      return Message.unSuccess(isSuccess);
    }
    if (Strings.isBlank(materialParam.getEndDate()) ||
        Strings.isBlank(materialParam.getStartDate())) {
      Pair<String, String> aYearStartEnd = RenderDateUtil.getRecent1Year();
      materialParam.setStartDate(aYearStartEnd.getKey());
      materialParam.setEndDate(aYearStartEnd.getValue());
    }
    materialParam.setSortType("sim");

    if (materialParam.getDegree() == null) materialParam.setDegree(0.3);
    materialParam.setSearchType("false");
    List<Hit<Material>> hits = searchById(materialParam, new String[]{"material_keywords"});
    if (hits.isEmpty()) {
      return Message.unSuccess("id 不正确");
    }

    List<String> searchingKeywords = new ArrayList<>();
    assert hits.get(0).source() != null;

    searchingKeywords.addAll(EsTypeTransUtil.entity2List(hits.get(0).source().getMaterialKeywords()));
    materialParam.setQueryStr(String.join(" ", searchingKeywords));
    materialParam.setPageSize(10);

    SearchRequest.Builder requestBuilder =  buildMaterialRequest.buildMaterialRequest(materialParam, true).sort((SortOptions) materialParam.get3Sorts().get(2));;
    JSONObject sim = new JSONObject();
    SearchRequest searchRequest = requestBuilder.build();
    getSimNews(getResponseEntity(searchRequest, materialParam), sim, materialParam);

    return Message.builder().code(200).message("success.").data(sim).build();
  }
}
